import { useObservable } from '@gnlab/utils/env-react/rx'
import { App, Input } from 'antd'
import { useStreams } from '@/lib/utils'
import services from '@/services'
import { API } from '@/services/common/api'
import { TopicObservables } from '@/services/common/qywx-mqtt'
import { Status } from '@/services/container'

export { Status }

/**
 * 获取容器信息，以完成企业微信二维码登录
 *
 * onLoggedIn(): 发现企业微信待登录成功后，会触发此回调
 */
export function useContainer(onLoggedIn?: () => void) {
  const [usable] = useStreams(services.container.usable)

  // 记录最近一次使用的 container（原 container 变量的值总是最新的，无法用来判断登录的微信是不是之前展示的 container 的)
  const [latestContainer, setLatestContaienr] = useState(() =>
    usable.status === Status.Normal ? usable.data : null,
  )
  useEffect(() => {
    if (usable.status === Status.Normal) setLatestContaienr(usable.data)
  }, [usable])

  // 确认企业微信登录，触发通知
  useObservable(
    services.qywxs.events,
    event => {
      if (event.type === 'found' && event.info.hostname === latestContainer?.hostname) {
        if (onLoggedIn) onLoggedIn()
      }
    },
    [onLoggedIn, latestContainer],
  )

  useEffect(() => {
    // 初始化时触发一次加载
    void services.container.getUsable()
    return () => {
      // 离开时遗忘当前取得的容器
      void services.container.forget()
    }
  }, [])

  const refresh = useCallback(() => {
    void services.container.getUsable()
  }, [])

  return {
    usable,
    refresh,
  }
}

/**
 * 处理微信扫码状态
 */
export interface ScanData {
  status: number // 1 已扫码  4 取消扫码
  qrcode_key: string
}

export function useScanStatus(hostname: string | undefined, refresh: () => void) {
  const { modal, message } = App.useApp()
  const [scaned, setScaned] = useState(false)

  useEffect(() => {
    setScaned(false)
    if (hostname === undefined) return

    const observables = new HostObservables(hostname)
    const subscription = observables
      .hookPlain<ScanData>(11174)
      .subscribe(({ data: { status, qrcode_key } }) => {
        if (status === 1) {
          setScaned(true)
        } else if (status === 4) {
          setScaned(false)
          refresh()
        } else if (status === 10) {
          showCodeModal(qrcode_key)
        }
      })

    function showCodeModal(qrcode_key: string, codeInvalidMsg = '') {
      let code = ''
      modal.confirm({
        title: '请输入登录验证码',
        content: <div css={{ padding: '20px 0' }}>
          <Input
            placeholder="企微登录验证码"
            onChange={e => {
              code = e.target.value
            }}
          />
          {codeInvalidMsg ? (
            <div css={{ marginTop: '12px', color: 'red' }}>{codeInvalidMsg}</div>
          ) : null}
        </div>,
        onOk: async () => verify(code, qrcode_key),
      })
    }
    async function verify(verifyCode: string, qrcode_key: string) {
      const res = await API<{ errcode: number; errmsg: string }>('/Container/QrcodeVerify', {
        data: {
          hostname,
          key: qrcode_key,
          code: verifyCode,
        },
      })
      if (res.success) {
        if (res.data.errcode < 0)
          showCodeModal(qrcode_key, `验证未通过（${res.data.errcode}: ${res.data.errmsg}）`)
        else void message.success('验证码已提交')
      } else {
        showCodeModal(qrcode_key, '请求失败')
      }
    }

    return () => {
      subscription.unsubscribe()
      observables.unsubscribe()
    }
  }, [hostname, refresh, modal, message])

  return { scaned }
}

/**
 * 监听特定 hostname 的消息
 */
export class HostObservables extends TopicObservables {
  constructor(readonly hostname: string) {
    // 因为写入 this.hostname 比 super.constructor() 晚，
    // 所以传入一个 Promise，让 super 晚一点再读取 topics
    super(services.mqtt.connection, Promise.resolve([]))
  }

  get topics() {
    return [{ accountId: '', topicId: `quntool/wxw/${this.hostname}` }]
  }
}
